/******************************************************************************* * Copyright (c) 2005, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.browser; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.mozilla.*; import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.widgets.*; @SuppressWarnings({"rawtypes", "unchecked"}) class MozillaDelegate { Browser browser; Vector childWindows = new Vector (9); static long /*int*/ MozillaProc; static Callback SubclassProc; static Callback SubclassProc_UpdateUIState; MozillaDelegate (Browser browser) { super (); this.browser = browser; } static Browser findBrowser (long /*int*/ handle) { Display display = Display.getCurrent (); return (Browser)display.findWidget (handle); } static String getCacheParentPath () { /* Use the character encoding for the default locale */ TCHAR buffer = new TCHAR (0, OS.MAX_PATH); if (OS.SHGetFolderPath (0, OS.CSIDL_LOCAL_APPDATA, 0, OS.SHGFP_TYPE_CURRENT, buffer) == OS.S_OK) { return buffer.toString (0, buffer.strlen ()) + Mozilla.SEPARATOR_OS + "eclipse"; //$NON-NLS-1$ } return getProfilePath (); } static String[] getJSLibraryNames () { return new String[] {"mozjs.dll", "xul.dll"}; //$NON-NLS-1$ //$NON-NLS-2$ } static String getJSLibraryName_Pre4 () { return "js3250.dll"; //$NON-NLS-1$ } static String getLibraryName () { return "xpcom.dll"; //$NON-NLS-1$ } static String getProfilePath () { String baseDir; /* Use the character encoding for the default locale */ TCHAR buffer = new TCHAR (0, OS.MAX_PATH); if (OS.SHGetFolderPath (0, OS.CSIDL_APPDATA, 0, OS.SHGFP_TYPE_CURRENT, buffer) == OS.S_OK) { baseDir = buffer.toString (0, buffer.strlen ()); } else { baseDir = System.getProperty("user.home"); //$NON-NLS-1$ } return baseDir + Mozilla.SEPARATOR_OS + "Mozilla" + Mozilla.SEPARATOR_OS + "eclipse"; //$NON-NLS-1$ //$NON-NLS-2$ } static String getSWTInitLibraryName () { return "swt-xulrunner"; //$NON-NLS-1$ } static void loadAdditionalLibraries (String mozillaPath) { } static char[] mbcsToWcs (String codePage, byte[] buffer) { char[] chars = new char[buffer.length]; int charCount = OS.MultiByteToWideChar (OS.CP_ACP, OS.MB_PRECOMPOSED, buffer, buffer.length, chars, chars.length); if (charCount == chars.length) return chars; char[] result = new char[charCount]; System.arraycopy (chars, 0, result, 0, charCount); return result; } static boolean needsSpinup () { return false; } static boolean supportsXULRunner17 () { return true; } static byte[] wcsToMbcs (String codePage, String string, boolean terminate) { int byteCount; char[] chars = new char[string.length()]; string.getChars (0, chars.length, chars, 0); byte[] bytes = new byte[byteCount = chars.length * 2 + (terminate ? 1 : 0)]; byteCount = OS.WideCharToMultiByte (OS.CP_ACP, 0, chars, chars.length, bytes, byteCount, null, null); if (terminate) { byteCount++; } else { if (bytes.length != byteCount) { byte[] result = new byte[byteCount]; System.arraycopy (bytes, 0, result, 0, byteCount); bytes = result; } } return bytes; } static long /*int*/ windowProc (long /*int*/ hwnd, long /*int*/ msg, long /*int*/ wParam, long /*int*/ lParam) { switch ((int)/*64*/msg) { case OS.WM_UPDATEUISTATE: /* * In XULRunner 17, calling the default windowProc for WM_UPDATEUISTATE message * terminates the program. Workaround is to prevent the call to default windowProc. */ return 0; case OS.WM_ERASEBKGND: RECT rect = new RECT (); OS.GetClientRect (hwnd, rect); OS.FillRect (wParam, rect, OS.GetSysColorBrush (OS.COLOR_WINDOW)); break; } return OS.CallWindowProc (MozillaProc, hwnd, (int)/*64*/msg, wParam, lParam); } static long /*int*/ windowProc1 (long /*int*/ hwnd, long /*int*/ msg, long /*int*/ wParam, long /*int*/ lParam) { switch ((int)/*64*/msg) { case OS.WM_UPDATEUISTATE: /* * In XULRunner 17, calling the default windowProc for WM_UPDATEUISTATE message * terminates the program. Workaround is to prevent the call to default windowProc. */ return 0; } return OS.CallWindowProc (MozillaProc, hwnd, (int)/*64*/msg, wParam, lParam); } void addWindowSubclass () { long /*int*/ hwndChild = OS.GetWindow (browser.handle, OS.GW_CHILD); if (SubclassProc == null) { SubclassProc = new Callback (MozillaDelegate.class, "windowProc", 4); //$NON-NLS-1$ MozillaProc = OS.GetWindowLongPtr (hwndChild, OS.GWL_WNDPROC); } OS.SetWindowLongPtr (hwndChild, OS.GWL_WNDPROC, SubclassProc.getAddress ()); } int createBaseWindow (nsIBaseWindow baseWindow) { return baseWindow.Create (); } long /*int*/ getHandle () { return browser.handle; } long /*int*/ getSiteWindow () { /* * As of XULRunner 4, XULRunner's printing facilities on Windows destroy * the HWND that is returned from here once the print dialog is dismissed * (originating bug: https://bugzilla.mozilla.org/show_bug.cgi?id=588735 ). * For this scenario it is now expected that the handle that is returned * here is a child of the browser handle, not the browser handle itself. * * The other scenario that requests this handle is the Mozilla.getBrowser() * implementation. This method's GetSiteWindow() invocation is surrounded * by boolean flags to help differentiate it from the printing scenario, * since Mozilla.getBrowser() does not destroy the handle it receives back. * * All children that are created here are stored and then destroyed once * the current page is left. This is guard code that should only be needed * if Mozilla.getSiteWindow() is ever invoked by a path other than one of * the two described above. */ if (Mozilla.IsPre_4 || Mozilla.IsGettingSiteWindow) { return getHandle (); } Composite child = new Composite (browser, SWT.NONE); childWindows.addElement (child); return child.handle; } void handleFocus () { } void handleMouseDown () { } boolean hookEnterExit () { return true; } void init () { if (!Mozilla.IsPre_4) { /* * In XULRunner versions > 4, sending WM_GETDLGCODE to a WM_KEYDOWN's MSG hwnd answers 0 * instead of the expected DLGC_WANTALLKEYS. This causes the default traversal framework * perform traversals outside of the Browser when it should not. Hook a Traverse listener * to work around these problems. */ browser.addListener (SWT.Traverse, new Listener () { public void handleEvent (Event event) { switch (event.detail) { case SWT.TRAVERSE_RETURN: case SWT.TRAVERSE_ESCAPE: { /* always veto the traversal */ event.doit = false; break; } case SWT.TRAVERSE_TAB_NEXT: case SWT.TRAVERSE_TAB_PREVIOUS: { /* veto the traversal whenever an element in the browser has focus */ long /*int*/[] result = new long /*int*/[1]; int rc = XPCOM.NS_GetServiceManager (result); if (rc != XPCOM.NS_OK) Mozilla.error (rc); if (result[0] == 0) Mozilla.error (XPCOM.NS_NOINTERFACE); nsIServiceManager serviceManager = new nsIServiceManager (result[0]); result[0] = 0; byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_FOCUSMANAGER_CONTRACTID, true); rc = serviceManager.GetServiceByContractID (aContractID, nsIFocusManager.NS_IFOCUSMANAGER_10_IID, result); serviceManager.Release (); if (rc == XPCOM.NS_OK && result[0] != 0) { nsIFocusManager focusManager = new nsIFocusManager (result[0]); result[0] = 0; rc = focusManager.GetFocusedElement (result); focusManager.Release (); event.doit = result[0] == 0; if (rc == XPCOM.NS_OK && result[0] != 0) { new nsISupports (result[0]).Release (); } } break; } } } }); /* children created in getSiteHandle() should be destroyed whenever a page is left */ browser.addLocationListener (new LocationAdapter () { public void changing (LocationEvent event) { Enumeration enumeration = childWindows.elements (); while (enumeration.hasMoreElements ()) { ((Composite)enumeration.nextElement ()).dispose (); } childWindows.clear (); } }); } } void onDispose (long /*int*/ embedHandle) { if (SubclassProc == null && SubclassProc_UpdateUIState == null) return; long /*int*/ hwndChild = OS.GetWindow (browser.handle, OS.GW_CHILD); OS.SetWindowLongPtr (hwndChild, OS.GWL_WNDPROC, MozillaProc); childWindows = null; browser = null; } void removeWindowSubclass () { long /*int*/ hwndChild = OS.GetWindow (browser.handle, OS.GW_CHILD); if (Mozilla.IsPre_17) { if (SubclassProc != null) { OS.SetWindowLongPtr (hwndChild, OS.GWL_WNDPROC, MozillaProc); } } else { if (SubclassProc_UpdateUIState == null) { SubclassProc_UpdateUIState = new Callback (MozillaDelegate.class, "windowProc1", 4); //$NON-NLS-1$ } OS.SetWindowLongPtr (hwndChild, OS.GWL_WNDPROC, SubclassProc_UpdateUIState.getAddress ()); } } boolean sendTraverse () { return false; } void setSize (long /*int*/ embedHandle, int width, int height) { } }